package com.example.gobang.service;

import com.example.gobang.constant.Constants;
import com.example.gobang.manager.OnlineUserManager;
import com.example.gobang.manager.RoomManager;
import com.example.gobang.mapper.UserMapper;
import com.example.gobang.model.*;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.transaction.interceptor.TransactionAspectSupport;
import org.springframework.web.socket.TextMessage;
import org.springframework.web.socket.WebSocketSession;

import java.io.IOException;

@Service
@Slf4j
public class RoomService {
    @Autowired
    private RoomManager roomManager;
    @Autowired
    private OnlineUserManager onlineUserManager;
    @Autowired
    private ObjectMapper objectMapper;
    @Autowired
    private UserMapper userMapper;
    // 进行落子操作
    public void putChess(GameRequest request, UserInfo userInfo) throws IOException {
        // 获取房间
        Room room = roomManager.getRoomByUserId(userInfo.getUserId());
        // 判断当前玩家是 玩家1 还是 玩家2
        int chess = userInfo.getUserId() == room.getUser1().getUserId() ? 1: 2;
        // 获取棋子位置
        int row = request.getRow();
        int col = request.getCol();
        // 当前位置是否有子
        if(!room.isEmpty(row, col)) {
            log.info("已禁止 玩家 {} 在 {} 行 {} 列重复落子！", userInfo.getUserName(), row, col);
            return;
        }
        room.putChess(row, col, chess);
        // 打印棋盘信息，方便观察
        room.printBoard();
        // 进行胜负判断
        int winner = room.checkWinner( row, col, chess);
        // 若胜负已分，则销毁房间
        if(winner != 0) {
            log.info("房间 {} 游戏已结束，获胜方为 {}", room.getRoomId(), winner);
            // TODO 更新玩家分数
            int loser = (room.getUser1().getUserId() == winner) ? room.getUser2().getUserId() : room.getUser1().getUserId();
            updateScore(winner, loser);
            log.info("玩家 {} 分数+30，玩家 {} 分数-30", winner, loser);
            // 销毁房间
            roomManager.remove(room.getRoomId(), room.getUser1().getUserId(), room.getUser2().getUserId());
        }
        // 通知玩家
        WebSocketSession session1 = onlineUserManager.getFromRoom(room.getUser1().getUserId());
        WebSocketSession session2 = onlineUserManager.getFromRoom(room.getUser2().getUserId());
        GameResponse response1 = new GameResponse(room.getRoomId(), userInfo.getUserId(), row, col, winner);
        GameResponse response2 = new GameResponse(room.getRoomId(), userInfo.getUserId(), row, col, winner);
        session1.sendMessage(new TextMessage(objectMapper.writeValueAsString(Result.success(response1, Constants.PUT_CHESS))));
        session2.sendMessage(new TextMessage(objectMapper.writeValueAsString(Result.success(response2, Constants.PUT_CHESS))));
    }

    /**
     * 更新数据库中玩家分数
     * 要么都更新成功，要么都更新失败
     * @param winner
     * @param loser
     */
    @Transactional
    public void updateScore(int winner, int loser) {
        int winResult = userMapper.userWin(winner);
        int loseResult = userMapper.userLose(loser);
        if(winResult <= 0 || loseResult <= 0) {
            //手动回滚事务
            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
            log.error("玩家{} {} 分数更新失败！", winner, loser);
        }
    }
}
